package com.ruoyi.spspublic.service.impl;

import cn.hutool.http.HttpUtil;
import com.ruoyi.common.config.UploadConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.date.DateJsonConverter;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.spspublic.domain.TMisBlob;
import com.ruoyi.spspublic.domain.dto.PartymanFlowFileDto;
import com.ruoyi.spspublic.domain.dto.TMisBlobDownloadDTO;
import com.ruoyi.spspublic.mapper.TMisBlobMapper;
import com.ruoyi.spspublic.service.ITMisBlobService;
import com.ruoyi.system.service.ISysDictDataService;
import io.jsonwebtoken.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.uuid.IdUtils.simpleUUID;

/**
 * 业务附件Service业务层处理
 *
 * @author wangwei
 * @date 2023-06-19
 */
@Service
@Slf4j
public class TMisBlobServiceImpl implements ITMisBlobService {
    @Autowired
    private TMisBlobMapper tMisBlobMapper;

    @Resource
    private ISysDictDataService sysDictDataService;

    @Autowired
    private UploadConfig uploadConfig;

    @Resource
    private DateJsonConverter dateJsonConverter;

    @Resource
    private RedisCache redisCache;

    private static final String INNER_FILE = "01";
    private static final String OUTER_FILE = "02";
    private static final String SUPER_LINK = "03";

    /**
     * 查询业务附件
     *
     * @param ctId 业务附件ID
     * @return 业务附件
     */
    @Override
    public TMisBlob selectTMisBlobById(String ctId) {
        return tMisBlobMapper.selectTMisBlobById(ctId);
    }

    /**
     * 查询业务附件列表
     *
     * @param tMisBlob 业务附件
     * @return 业务附件
     */
    @Override
    public List<TMisBlob> selectTMisBlobList(TMisBlob tMisBlob) {
        return tMisBlobMapper.selectTMisBlobList(tMisBlob);
    }

    /**
     * 新增业务附件
     *
     * @param tMisBlob 业务附件
     * @return 结果
     */
    @Override
    public int insertTMisBlob(TMisBlob tMisBlob) {
        tMisBlob.setCtId(IdUtils.simpleUUID());
        tMisBlob.setCtType(SUPER_LINK);
        tMisBlob.setDtDate(DateUtils.getNowDate());
        // 其他新增需要从前台传递
        return tMisBlobMapper.insertTMisBlob(tMisBlob);
    }

    /**
     * 修改业务附件
     *
     * @param tMisBlob 业务附件
     * @return 结果
     */
    @Override
    public int updateTMisBlob(TMisBlob tMisBlob) {
        return tMisBlobMapper.updateTMisBlob(tMisBlob);
    }

    /**
     * 批量删除业务附件
     *
     * @param ctIds 需要删除的业务附件ID
     * @return 结果
     */
    @Override
    public int deleteTMisBlobByIds(String[] ctIds) {
        return tMisBlobMapper.deleteTMisBlobByIds(ctIds);
    }

    @Override
    public int deleteTMisBlobByIdPs(String ctIdp) {
        String[] type = {"01"};
        TMisBlob blob = new TMisBlob();
        blob.setCtIdP(ctIdp);
        blob.setCtTypeList(type);
        List<TMisBlob> tMisBlobList = tMisBlobMapper.selectTMisBlobList(blob);
        if (tMisBlobList.size() == 0) {
            return 1;
        }
        return tMisBlobMapper.deleteTMisBlobByIdP(ctIdp);
    }

    /**
     * 删除业务附件信息
     *
     * @param ctId 业务附件ID
     * @return 结果
     */
    @Override
    public int deleteTMisBlobById(String ctId) {
        return tMisBlobMapper.deleteTMisBlobById(ctId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult batchUpload(TMisBlob tMisBlob, MultipartFile file) {
        // todo 这是label
        // List<String> allowedUploadType = sysDictDataService.selectDictLabelList("allowed_upload_type");
        List<String> allowedUploadType = null;

        //        for (MultipartFile file : multipartFiles) {
        String extension = FileUploadUtils.getExtension(file);
        if (!allowedUploadType.contains(extension.toLowerCase())) {
            throw new CustomException("上传的格式不被支持");
        }
        long fileSize = file.getSize();
        if (fileSize > uploadConfig.getMaximumFileSize()) {
            throw new CustomException("上传文件大小超过限制");
        }
        String trimProfileName = "";
        try {
            extension = "." + extension;
            trimProfileName = file.getOriginalFilename().replace(extension, "");
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        // todo 这个converter需要测试
        if (trimProfileName.contains("..")) {
            throw new CustomException("非法文件名，文件名称不能包含’..‘");
        }
        extension = extension.toLowerCase();
        //            String now = null == tMisBlob.getDtDate() ? DateUtils.getDate() :
        // dateJsonConverter.toJson(tMisBlob.getDtDate());
        Date date = null == tMisBlob.getDtDate() ? DateUtils.getNowDate() : tMisBlob.getDtDate();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String now = df.format(date);
        String[] yearMonthDay = now.split("-");
        String ctFile = File.separator + yearMonthDay[0] + File.separator + yearMonthDay[1];
        //        String ctFile = File.separator + tMisBlob.getCtFunNo() + File.separator +
        // yearMonthDay[0] + File.separator + yearMonthDay[1];
        String shortPath =
                uploadConfig.getRootUploadPath() + yearMonthDay[0] + File.separator + yearMonthDay[1];
        //        String shortPath = uploadConfig.getRootUploadPath() + tMisBlob.getCtFunNo() +
        // File.separator + yearMonthDay[0] + File.separator + yearMonthDay[1];
        //        String primaryKey = UUID.randomUUID().toString();
        String primaryKey = IdUtils.simpleUUID();
        //            String fileName = primaryKey + "_" + file.getOriginalFilename();
        /*TMisBlob tMisBlobToSave =
                TMisBlob.builder()
                        //                .ctFunNo(tMisBlob.getCtFunNo())
                        .ctIdP(tMisBlob.getCtIdP())
                        .ctName(trimProfileName)
                        .ctId(primaryKey)
                        .ctFileType(extension)
                        .ctType(INNER_FILE)
                        .amSize(fileSize)
                        .ctFile(ctFile)
                        .dtDate(date)
                        .build();*/

        TMisBlob tMisBlobToSave = new TMisBlob();
        // 创建保存目录
        //            String basePath = uploadConfig.getRootUploadPath() + tMisBlob.getCtFunNo();
        File localTempFile = new File(shortPath + File.separator + primaryKey + extension);
        //        File localTempFile = new File(shortPath + File.separator + primaryKey + "_" +
        // file.getOriginalFilename());
        try {
            if (!localTempFile.getParentFile().getParentFile().getParentFile().exists()) {
                localTempFile.getParentFile().getParentFile().getParentFile().mkdirs();
            }
            if (!localTempFile.getParentFile().getParentFile().exists()) {
                localTempFile.getParentFile().getParentFile().mkdirs();
            }
            if (!localTempFile.getParentFile().exists()) {
                localTempFile.getParentFile().mkdirs();
            }
            if (!localTempFile.exists()) {
                localTempFile.createNewFile();
            }
        } catch (IOException e) {
            throw new CustomException("文件夹创建失败，请联系管理员");
        }

        try {
            file.transferTo(localTempFile);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException("上传文件失败");
        }
        tMisBlobMapper.insertTMisBlob(tMisBlobToSave);
        //        }
        return AjaxResult.success("文件已成功上传", tMisBlobToSave);
    }

    @Override
    public AjaxResult download(TMisBlobDownloadDTO tMisBlob, HttpServletResponse response) {
        verifyToken(tMisBlob.getUuid(), tMisBlob.getCtId());
        AjaxResult ajaxResult = AjaxResult.success();
        TMisBlob targetData = tMisBlobMapper.selectTMisBlobById(tMisBlob.getCtId());
        try {
            //            String filePath = targetData.getCtFile() + File.separator + tMisBlob.getCtId() +
            // "_" + targetData.getCtName() + targetData.getCtType();
            String filePath = getFilePath(targetData);
            //            String filePath = uploadConfig.getServerName() + Constants.RESOURCE_PREFIX +
            // targetData.getCtFile() + File.separator + tMisBlob.getCtId() + "_" + targetData.getCtName()
            // + targetData.getCtType();
            if (filePath.contains("..")) {
                throw new CustomException(StringUtils.format("资源文件({})非法，不允许下载。 ", targetData.getCtName()));
            }
          /*  FileUtils.streamDownload(
                    filePath, response, targetData.getCtName(), targetData.getCtFileType());*/
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ajaxResult;
    }

    public String getFilePath(TMisBlob blob) {
        String filePath =
                uploadConfig.getRootUploadPath()
                        + blob.getCtFile()
                        + File.separator
                        + blob.getCtId()
                        + blob.getCtFileType();
        return filePath;
    }

    /**
     * .sql 文件下载
     *
     * @param tMisBlob
     * @return
     */
    public AjaxResult sqlDownload(String filePath, HttpServletResponse response) {
        AjaxResult ajaxResult = AjaxResult.success();
        // try {

        // todo 正式环境
        // String filePath = uploadConfig.getRootUploadPath() + targetData.getCtFile() + File.separator
        // + tMisBlob.getCtId() + targetData.getCtFileType();

        // todo 测试环境
        // String filePath = uploadConfig.getRootUploadPath() + targetData.getCtFile() + File.separator
        // + tMisBlob.getCtId() + targetData.getCtFileType();

        File file = new File(filePath);
        // String name = file.getName();
        String fileName = file.getName().substring(0, file.getName().lastIndexOf("."));

        String ctFileType = ".sql";
        try {
            //   FileUtils.streamDownload(filePath, response, fileName, ctFileType);
        } catch (Exception e) {
            e.getMessage();
        }
        // } catch (Exception e) {
        //   e.printStackTrace();
        // }
        ajaxResult.put("data", file);
        return ajaxResult;
    }

    @Override
    public AjaxResult handlePreview(TMisBlobDownloadDTO tMisBlob) {
        verifyToken(tMisBlob.getUuid(), tMisBlob.getCtId());
        TMisBlob targetData = tMisBlobMapper.selectTMisBlobById(tMisBlob.getCtId());
        //        String filePath = uploadConfig.getRootUploadPath() + tMisBlob.getCtFunNo() +
        // File.separator + tMisBlob.getCtName();
        String filePath =
//                tMisBlob.getUrl()
                uploadConfig.getServerName()
                        + Constants.RESOURCE_PREFIX
                        + targetData.getCtFile()
                        + File.separator
                        + tMisBlob.getCtId()
                        + targetData.getCtFileType();
        if (filePath.contains("..")) {
            throw new CustomException(StringUtils.format("资源文件({})非法", targetData.getCtName()));
        }
        String firstEncode = Base64.encode(filePath.getBytes(StandardCharsets.UTF_8));
        return AjaxResult.success("code", firstEncode);
    }

    @Override
    public void generateDownloadToken(String uuid, List<TMisBlob> list) {
        String token = "";
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        token += sysUser.getUserName() + "; ";
        token += list.stream().map(TMisBlob::getCtId).collect(Collectors.joining(",")) + "; ";
        redisCache.setCacheObject(uuid, token, 30, TimeUnit.MINUTES);
    }

    private void verifyToken(String uuid, String ctId) {
        String token = redisCache.getCacheObject(uuid);
        Assert.notNull(token, "下载页面已过期，请重新刷新界面");
        try {
            String[] tokenSplit = token.split(";");
            if (!(SecurityUtils.getUsername().equals(tokenSplit[0].trim())
                    && tokenSplit[1].contains(ctId))) {
                throw new CustomException("非法Token");
            }
        } catch (Exception e) {
            throw new CustomException("非法Token");
        }
    }

    @Override
    public AjaxResult uploadFileImage(MultipartFile file, String funno) {
        if (file.isEmpty()) {
            return AjaxResult.error("上传图片不能为空");
        }
        //List<String> uploadimageType = sysDictDataService.selectDictLabelList("uploadimage_type");
        List<String> uploadimageType = null;
        String extension = FileUploadUtils.getExtension(file);
        if (!uploadimageType.contains(extension.toLowerCase())) {
            return AjaxResult.error("上传的格式不被支持");
        }
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件的后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        Date date = DateUtils.getNowDate();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String now = df.format(date);
        String[] yearMonthDay = now.split("-");
        // 文件上传后的路径
        // String fileUrl="/"+ funno + "/" + yearMonthDay[0] + "/" + yearMonthDay[1] + "/";
        String filePath = uploadConfig.getRootUploadPath();
        String upload = "FileImage";
        fileName =
                upload
                        + "/"
                        + funno
                        + "/"
                        + yearMonthDay[0]
                        + "/"
                        + yearMonthDay[1]
                        + "/"
                        + simpleUUID()
                        + "."
                        + suffixName;
        // 给前台
        File fileUrl = new File(Constants.RESOURCE_PREFIX + "/" + fileName);

        File dest = new File(filePath + fileName);
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败");
        }
        return AjaxResult.success(fileUrl);
    }

    /***
     * 上传sql 文件
     * 系统初始化数据库
     * @param
     * @return
     */
    public AjaxResult uploadFileSql(MultipartFile file, String funno) {
        if (file.isEmpty()) {
            return AjaxResult.error("上传sql文件不能为空");
        }
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件的后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        Date date = DateUtils.getNowDate();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String now = df.format(date);
        String[] yearMonthDay = now.split("-");
        // 文件上传后的路径
        // String fileUrl="/"+ funno + "/" + yearMonthDay[0] + "/" + yearMonthDay[1] + "/";

        // todo 正式环境 文件path
        // String filePath = uploadConfig.getRootUploadPath();

        // todo 开发环境  文件path
        String filePath = "E:\\ZHENGERG\\ZHENGERGY-workspace\\party-mis\\data\\party-mis\\uploadPath";

        String upload = "FileSql";
        fileName =
                upload
                        + "/"
                        + funno
                        + "/"
                        + yearMonthDay[0]
                        + "/"
                        + yearMonthDay[1]
                        + "/"
                        + simpleUUID()
                        + "."
                        + suffixName;
        // 给前台
        File fileUrl = new File(Constants.RESOURCE_PREFIX + "/" + fileName);

        File dest = new File(filePath + fileName);
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败");
        }
        return AjaxResult.success(fileUrl);
    }

    @Override
    public List<TMisBlob> selectTMisBlobListByTMisBlob(TMisBlob tMisBlob) {
        return tMisBlobMapper.selectTMisBlobListByTMisBlob(tMisBlob);
    }

    /**
     * 党员发展流程附件
     *
     * @param partymanFlowFileDto
     * @return
     */
    @Override
    public List<PartymanFlowFileDto> partymanFlowFileList(PartymanFlowFileDto partymanFlowFileDto) {
        return tMisBlobMapper.selectPartymanFlowListFileList(partymanFlowFileDto);
    }

    @Override
    public void simpleUpload(String filePath, TMisBlob tMisBlob) {
        Pattern pattern = Pattern.compile("/([^/]+)$");
        Matcher matcher = pattern.matcher(filePath);
        String tmpFileName;
        if (matcher.find()) {
            tmpFileName = matcher.group(1);
        } else {
            tmpFileName = filePath;
        }
        File networkTmpFile = new File(uploadConfig.getRootUploadPath() + "tmp" + File.separator + tmpFileName);
        HttpUtil.downloadFile(filePath, networkTmpFile);
        String extension = FilenameUtils.getExtension(networkTmpFile.getName());
        String trimProfileName = "";
        try {
            extension = "." + extension;
            trimProfileName = networkTmpFile.getName().replace(extension, "");
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        extension = extension.toLowerCase();
        Date date = null == tMisBlob.getDtDate() ? DateUtils.getNowDate() : tMisBlob.getDtDate();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String now = df.format(date);
        String[] yearMonthDay = now.split("-");
        String ctFile = File.separator + yearMonthDay[0] + File.separator + yearMonthDay[1];
        String shortPath = uploadConfig.getRootUploadPath() + yearMonthDay[0] + File.separator + yearMonthDay[1];
        String primaryKey = IdUtils.simpleUUID();
        /*TMisBlob tMisBlobToSave =
                TMisBlob.builder()
                        .ctIdP(tMisBlob.getCtIdP())
                        .ctName(trimProfileName)
                        .ctId(primaryKey)
                        .ctFileType(extension)
                        .ctType(INNER_FILE)
                        .amSize(0L)
                        .ctFile(ctFile)
                        .dtDate(date)
                        .build();*/
        TMisBlob tMisBlobToSave = new TMisBlob();
        // 创建保存目录
        File localTempFile = new File(shortPath + File.separator + primaryKey + extension);
        try {
            if (!localTempFile.getParentFile().getParentFile().getParentFile().exists()) {
                localTempFile.getParentFile().getParentFile().getParentFile().mkdirs();
            }
            if (!localTempFile.getParentFile().getParentFile().exists()) {
                localTempFile.getParentFile().getParentFile().mkdirs();
            }
            if (!localTempFile.getParentFile().exists()) {
                localTempFile.getParentFile().mkdirs();
            }
            if (!localTempFile.exists()) {
                localTempFile.createNewFile();
            }
        } catch (IOException e) {
            //   FileUtils.deleteTempFile(networkTmpFile);
            throw new CustomException("文件夹创建失败，请联系管理员");
        }
        try {
            FileUtils.copyFile(networkTmpFile, localTempFile);
        } catch (IOException e) {
            e.printStackTrace();
            //FileUtils.deleteTempFile(networkTmpFile);
            throw new CustomException("保存失败，请联系管理员");
        }
        //FileUtils.deleteTempFile(networkTmpFile);
        tMisBlobMapper.insertTMisBlob(tMisBlobToSave);
    }
}
